function graphChart() {
    console.log('graphChart')
    var width = 500,
        height = 500,
        fillNode = "#07a0c3",
        strokeNode = "#fff",
        fillNodeHover = "#E47F74",
        fillNeighbors = "#f0c808",
        fillText = "#333",
        strokeLink = d3.rgb(150, 150, 150, 0.2),
        strokeLinkHover = d3.rgb(50, 50, 50, 1),
        minRadius = 8,
        radius = function (node) {
            return minRadius + node.weight * 3;
        };
    var dispatch;
    var miserables;
    function chart(selection) {
        selection.each(function (data) {
            console.log('--=--=')
            console.log(data)
            var zoom = d3
                .zoom()
                .scaleExtent([1 / 4, 5])
                .on("zoom", zoomed);

            var svg = d3
                .select(this)
                .attr("width", width)
                .attr("height", height)
                .call(zoom);

            const simulation = d3
                .forceSimulation(data.nodes)
                .force(
                    "link",
                    d3
                        .forceLink(data.edges)
                        .id((d) => d.id)
                        .distance(600)
                )
                .force(
                    "charge",
                    d3.forceManyBody().strength((d) => -radius(d) * 50)
                )
                .force("center", d3.forceCenter(width / 3, height / 3))
                .force("x", d3.forceX())
                .force("y", d3.forceY());

            function zoomed() {
                let scale = d3.event.transform.k;
                g.attr(
                    "transform",
                    `translate(${d3.event.transform.x}, ${d3.event.transform.y}) scale(${scale})`
                );
            }

            const dragNode = function (simulation) {
                function dragstarted(d) {
                    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
                    d.fx = d.x;
                    d.fy = d.y;
                }

                function dragged(d) {
                    d.fx = d3.event.x;
                    d.fy = d3.event.y;
                }

                function dragended(d) {
                    if (!d3.event.active) simulation.alphaTarget(0);
                    d.fx = null;
                    d.fy = null;
                }

                return d3
                    .drag()
                    .on("start", dragstarted)
                    .on("drag", dragged)
                    .on("end", dragended);
            };

            const getNeighbors = function (node) {
                var id = d3.select(node).attr("id");
                // Filter the links about the selected character
                var neighbors = data.edges.filter(
                    (link) => link.source.id === id || link.target.id === id
                );

                // Creates an array with all the node id that has interacted with the selected node
                // The prepend hashtag will help us to select in CSS th nodes
                const neighbors_nodes = neighbors.map(function (link) {
                    if (link.source.id === id) {
                        return "#" + link.target.id;
                    } else {
                        return "#" + link.source.id;
                    }
                });

                var neighbors_edges = neighbors
                    .map((d) => "#link_" + d.index)
                    .join(",");

                return {
                    nodes: neighbors_nodes.join(),
                    links: neighbors_edges
                };
            };

            const handleMouseOver = function (d, i) {
                var neighbors = getNeighbors(this);

                d3.select(this)
                    .transition()
                    .select("circle")
                    .attr("fill", fillNodeHover);

                d3.select(this).transition().select("text").attr("fill-opacity", 1);

                d3.selectAll(neighbors.nodes)
                    .select("circle")
                    .transition()
                    .attr("fill", fillNeighbors);

                d3.selectAll(neighbors.nodes)
                    .select("text")
                    .transition()
                    .attr("fill-opacity", 1);

                d3.selectAll(neighbors.links)
                    .transition()
                    .attr("stroke", strokeLinkHover);
            };

            const handleMouseOut = function (d, i) {
                var neighbors = getNeighbors(this);
                d3.select(this).select("circle").transition().attr("fill", fillNode);

                d3.selectAll(".nodes text")
                    .filter((d, i) => d.weight < 10)
                    .transition()
                    .attr("fill-opacity", 0);

                d3.selectAll(neighbors.nodes)
                    .select("circle")
                    .transition()
                    .attr("fill", fillNode);

                d3.selectAll(neighbors.links).transition().attr("stroke", strokeLink);
            };

            const handleMouseClick = function (d, i) {
                // var neighbors = getNeighbors(this);
                // dispatch.call("nodeClick", this, d, neighbors);
            }

            var g = svg.append("g").attr("id", "force-directed-graph");

            svg.call(
                zoom.transform,
                d3.zoomIdentity.scale(0.6).translate(width / 2, height / 2)
            );

            var links = g
                .append("g")
                .attr("class", "links")
                .attr("stroke", strokeLink)
                .attr("stroke-opacity", 0.2)
                .selectAll("line")
                .data(data.edges)
                .enter()
                .append("line")
                .attr("stroke-width", 2)
                .attr("id", (d, i) => "link_" + i);

            var nodes = g
                .append("g")
                .attr("class", "nodes")
                .selectAll("circle")
                .data(data.nodes)
                .enter()
                .append("g")
                .attr("class", "node")
                .attr("id", (d) => d.id)
                .on("mouseover", handleMouseOver)
                .on("mouseout", handleMouseOut)
                .on("click", handleMouseClick)
                .call(dragNode(simulation));

            nodes
                .append("circle")
                .attr("r", (d) => radius(d))
                .attr("fill", fillNode)
                .attr("stroke", strokeNode)
                .attr("stroke-width", 3);

            nodes
                .append("text")
                .text((d) => d.label.toUpperCase())
                .attr("fill", fillText)
                .attr("fill-opacity", 1)
                .attr("font-size", (d) => d.weight * 1)
                .attr("text-anchor", "middle")
                .filter((d, i) => d.weight < 8)
                .attr("fill-opacity", 0)
                .attr("font-size", 15);

            simulation.on("tick", function () {
                links
                    .attr("x1", (d) => d.source.x)
                    .attr("y1", (d) => d.source.y)
                    .attr("x2", (d) => d.target.x)
                    .attr("y2", (d) => d.target.y);

                nodes
                    .selectAll("circle")
                    .attr("cx", (d) => d.x)
                    .attr("cy", (d) => d.y);

                nodes
                    .selectAll("text")
                    .attr("x", (d) => d.x)
                    .attr("y", (d) => d.y + radius(d) / 4);
            });
        });
    }

    chart.width = function (value) {
        if (!arguments.length) return width;
        width = value;
        return chart;
    };

    chart.height = function (value) {
        if (!arguments.length) return height;
        height = value;
        return chart;
    };

    chart.nodes = function (value) {
        if (!arguments.length) return nodes;
        nodes = value;
        return chart;
    };

    chart.edges = function (value) {
        if (!arguments.length) return edges;
        edges = value;
        return chart;
    };
    chart.miserables = function (value) {
        if (!arguments.length) return miserables;
        miserables = value;
        return chart;
    };

    chart.fillNode = function (value) {
        if (!arguments.length) return fillNode;
        fillNode = value;
        return chart;
    };

    chart.fillNodeHover = function (value) {
        if (!arguments.length) return fillNodeHover;
        fillNodeHover = value;
        return chart;
    };

    chart.fillNeighbors = function (value) {
        if (!arguments.length) return fillNeighbors;
        fillNeighbors = value;
        return chart;
    };

    chart.radius = function (value) {
        if (!arguments.length) return radius;
        radius = value;
        return chart;
    };

    chart.fillText = function (value) {
        if (!arguments.length) return fillText;
        fillText = value;
        return chart;
    };

    chart.strokeNode = function (value) {
        if (!arguments.length) return strokeNode;
        strokeNode = value;
        return chart;
    };

    chart.strokeLinkHover = function (value) {
        if (!arguments.length) return strokeLinkHover;
        strokeLinkHover = value;
        return chart;
    };

    chart.strokeLink = function (value) {
        if (!arguments.length) return strokeLink;
        strokeLink = value;
        return chart;
    };
    chart.dispatch = function (value) {
        console.log(value)
        if (!arguments.length) return dispatch;
        dispatch = value;
        return chart;
    }
    chart.update = function ({ nodes, edges }) {
        console.log('update', nodes, edges)
    }
    return chart;
}
